package chen.videoedit.continuousplay;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.view.Surface;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;

/**
 * Created by 15705 on 2016/11/14.
 * 连续视频解码
 */
public class VideoDecoderCore {


    private final ArrayList<String> list;
    private final Surface surface;
    private ArrayList<Pojo> pojos;
    public Boolean stop = false;

    public VideoDecoderCore(ArrayList<String> list, Surface surface) {
        this.list = list;
        this.surface = surface;
    }

    /**
     * 数据初始化
     */
    public void prepareDecode() throws IOException {
        if (pojos == null) {
            pojos = new ArrayList<Pojo>();
        } else {
            pojos.clear();
        }
        for (String s : list) {
            MediaExtractor extractor = new MediaExtractor();
            extractor.setDataSource(s);
            int trackCount = extractor.getTrackCount();
            for (int i = 0; i < trackCount; i++) {
                MediaFormat f = extractor.getTrackFormat(i);
                String mime = f.getString(MediaFormat.KEY_MIME);
                if (mime.startsWith("video/")) {
                    MediaCodec mediaCodec = MediaCodec.createDecoderByType(mime);
                    Pojo pojo = new Pojo();
                    pojo.setExtractor(extractor);
                    pojo.setFormat(f);
                    pojo.setTrack(i);
                    pojo.setMediaCodec(mediaCodec);
                    pojos.add(pojo);
                    break;
                }
            }
        }
    }

    /**
     * 解码开始
     */
    public void doDecode() {
        int s = pojos.size();
        for (int i = 0; i < s; i++) {
            Pojo pojo = pojos.get(i);
            if (stop) break;
            MediaExtractor extractor = pojo.getExtractor();
            MediaCodec mediaCodec = pojo.getMediaCodec();
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            mediaCodec.configure(pojo.getFormat(), surface, null, 0);
            mediaCodec.start();
            ByteBuffer[] input = mediaCodec.getInputBuffers();
            extractor.selectTrack(pojo.getTrack());
            while (true) {
                if (stop) break;
                int inputBufIndex = mediaCodec.dequeueInputBuffer(-1);
                if (inputBufIndex < 0) break;
                ByteBuffer inputBuffer = input[inputBufIndex];
                inputBuffer.clear();
                int size = extractor.readSampleData(inputBuffer, 0);
                if (size < 0) break;
                extractor.advance();//读取下一步
                long presentationTimeUs = extractor.getSampleTime();
                mediaCodec.queueInputBuffer(inputBufIndex, 0, size, presentationTimeUs, 0);//通知解码器数据放入
                int outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 1000);//获取解码数据
                if (stop) break;
                if (outputBufferIndex >= 0) {
                    try {
                        Thread.sleep(25);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mediaCodec.releaseOutputBuffer(outputBufferIndex, true);
                }
            }
            extractor.release();
            mediaCodec.stop();
            mediaCodec.release();
            pojo.setMediaCodec(null);
            pojo.setExtractor(null);
            pojo.setFormat(null);
            extractor = null;
            mediaCodec = null;
        }
        pojos.clear();
    }


    public class Pojo {
        private MediaExtractor extractor;
        private MediaFormat format;
        private int track;
        private int start;
        private int end;
        private MediaCodec mediaCodec;

        public MediaCodec getMediaCodec() {
            return mediaCodec;
        }

        public void setMediaCodec(MediaCodec mediaCodec) {
            this.mediaCodec = mediaCodec;
        }

        public MediaExtractor getExtractor() {
            return extractor;
        }

        public void setExtractor(MediaExtractor extractor) {
            this.extractor = extractor;
        }

        public int getEnd() {
            return end;
        }

        public void setEnd(int end) {
            this.end = end;
        }

        public int getStart() {
            return start;
        }

        public void setStart(int start) {
            this.start = start;
        }

        public int getTrack() {
            return track;
        }

        public void setTrack(int track) {
            this.track = track;
        }

        public MediaFormat getFormat() {
            return format;
        }

        public void setFormat(MediaFormat format) {
            this.format = format;
        }
    }


}
